<?php if (!defined('CORE_DIR')) die('Wrong entry point!');

/* 
 * Copyright 2010 Anton Muraviev a.k.a kuromaisu
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */

// =============================================================================
// Section: Session
// =============================================================================
// 
// Configuration namespace:
// 	session
// 
// Configuration options:
// 	id_ttl		-	(int) number seconds during which session id is valid.

Aero::define('AeroSession', AS_SINGLETON);

/* -----------------------------------------------------------------------------
 * Class: AeroSession
 * -----------------------------------------------------------------------------
 * 
 * A simple wrapper for native PHP session.
 * 
 */
class AeroSession 
{
	protected $session_id_ttl;
	
	/*
	 * Constructor
	 */
	public function __construct()
	{
		$this->session_id_ttl = Aero::option('session.id_ttl',7200);
		
		if (!isset($_SESSION))
		{
			session_start();
		}
		
		// check if session id needs regeneration
		if ($this->_hasIdExpired())
		{
			// regenerate session id (session data stays the
			// same, but old session storage is destroyed)
			$this->regenerateId();
		}
	}

	/*
	 * Method: regenerateId
	 * 
	 * Regenerates session id.
	 */
	public function regenerateId()
	{
		// copy old session data, including its id
		$old_session_id = session_id();
		$old_session_data = $_SESSION;

		// regenerate session id and store it
		session_regenerate_id();
		$new_session_id = session_id();

		// switch to the old session and destroy its storage
		session_id($old_session_id);
		@session_destroy();

		// switch back to the new session id and send the cookie
		session_id($new_session_id);
		session_start();

		// restore the old session data into the new session
		$_SESSION = $old_session_data;

		// update the session creation time
		$_SESSION[':session-regenerated:'] = time();

		// session_write_close() patch based on this thread
		// http://www.codeigniter.com/forums/viewthread/1624/
		// there is a question mark ?? as to side affects

		// end the current session and store session data.
		session_write_close();
	}

	/*
	 * Method: destroy
	 * 
	 * Destroys current session
	 */
	public function destroy()
	{
		$_SESSION = array();
		
		if (ini_get("session.use_cookies"))
		{
			$params = session_get_cookie_params();
			setcookie(session_name(), '', time() - 42000,
				$params["path"], $params["domain"],
				$params["secure"], $params["httponly"]
			);
		}
		
		session_destroy();
	}
	
	/*
	 * Method: _hasIdExpired
	 * 
	 * Checks if session has expired
	 */
	protected function _hasIdExpired()
	{
		if (!isset($_SESSION[':session-regenerated:']))
		{
			$_SESSION[':session-regenerated:'] = time();
			return false;
		}
		
		$expiry_time = time() - $this->session_id_ttl;
		
		if ($_SESSION[':session-regenerated:'] <=  $expiry_time)
		{
			return true;
		}
		
		return false;
	}

	/*
	 * Method: item
	 * 
	 * Returns value of the specified path or $default.
	 */
	public function item($path, $default = null)
	{
		return aero_get_nested_array_value($_SESSION, $path, $default);
	}
	
	/*
	 * Method: setData
	 * 
	 * Sets session attributes to the given values
	 */
	public function setItem($path, $value = null)
	{
		return aero_set_nested_array_value($_SESSION, $path, $value);
	}

	/*
	 * Method: unsetData
	 * 
	 * Erases given session attributes.
	 */
	public function unsetItem($path)
	{
		return aero_unset_nested_array_value($_SESSION, $path);
	}
}